package server

import (
	"fmt"
	"io/ioutil"
	"listExcel/util"
	"os"
	"path"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/andlabs/ui"

	"github.com/360EntSecGroup-Skylar/excelize/v2"

	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
)

var Mainwin *ui.Window

var ROOT_PATH string
var wg sync.WaitGroup
var maxChan int

var rfs []ExcelFile

type Msg struct {
	Cell    string
	NewCell string
}
type ExcelFile struct {
	EF *excelize.File
}

func HandleExcel(excel_file string) {
	ROOT_PATH = os.Getenv("ROOT_PATH")
	mainClass := os.Getenv("MainClass")
	subClass := os.Getenv("subClass")
	imgCol := os.Getenv("ImgCol")
	class, _ := getClass()
	fmt.Println(mainClass, subClass)
	fmt.Println("class")
	fmt.Println(class)
	sheet := os.Getenv("Sheet")

	datas, rows, f, maxRow := readExcel(excel_file, sheet, subClass)
	fmt.Println("maxRow:", maxRow)
	//fmt.Println(imgs)

	newList := make([]int, len(datas)+1)
	tmp := make([][]int, len(class)+1)

	fmt.Println(len(rows))
	for k, v := range rows {
		for i, j := range class {
			if len(tmp[i]) < 1 {
				tmp[i] = make([]int, 0, 1)
			}
			if strings.Contains(j, "+") {
				types := strings.Split(j, "+")
				require_num := len(types)
				for _, tt := range types {
					if strings.Contains(v, tt) {
						require_num -= 1
					}
				}
				if require_num < 1 {
					datas[k] = append(datas[k], j)
					tmp[i] = append(tmp[i], k)
					break
				}

			}
			if strings.Contains(v, j) {
				datas[k] = append(datas[k], j)
				tmp[i] = append(tmp[i], k)
				break
			}
			if i == len(class)-1 {
				datas[k] = append(datas[k], "其它")
				tmp[len(class)] = append(tmp[len(class)], k)
			}
		}

	}
	//还原队列
	nk := 0
	for _, m := range tmp {
		for _, l := range m {

			if nk < len(newList) {
				newList[nk] = l
			} else {
				newList = append(newList, l)
			}

			nk += 1

		}
	}
	rawSheet := sheet
	//保存
	Mode := os.Getenv("Mode")
	if Mode == "New" {
		f = excelize.NewFile()
	} else {
		sheet += "sort"
	}

	// Create a new sheet.
	index := f.NewSheet(sheet)
	// Set value of a cell.
	//写入头部
	for m, n := range datas[0] {
		f.SetCellValue(sheet, getCol(m)+"1", n)

	}
	rowH := os.Getenv("RowH")
	lineH := 30.0

	if rowH != "" {
		lineH, _ = strconv.ParseFloat(rowH, 64)
	} else {
		rowH = "30"
	}
	//新excel的行
	cur_row := 2

	// 限制一下 数量
	maxChan = 2

	if tmp := os.Getenv("MaxChan"); tmp != "" {
		maxChan, _ = strconv.Atoi(tmp)
	}
	fmt.Println("maxchan:", maxChan)

	rfs = make([]ExcelFile, maxChan, maxChan+1)

	//ch := make(chan bool, maxChan)
	startTime := time.Now().Unix()
	fmt.Println("startTime:", startTime)
	//fmt.Println(newList)

	for _, vv := range newList {

		if vv == 0 {
			continue
		}

		f.SetRowHeight(sheet, cur_row, lineH)
		if len(datas[vv]) < 2 || (datas[vv][0] == "" && datas[vv][1] == "") || (datas[vv][1] == "" && datas[vv][2] == "") {
			maxRow = cur_row
			continue
		}
		for mm, nn := range datas[vv] {

			f.SetCellValue(sheet, getCol(mm)+strconv.Itoa(cur_row), nn)
		}

		cur_row += 1
	}
	//拷贝图片
	if imgCol != "" {

		for ii := 0; ii < maxChan; ii++ {
			var rf ExcelFile
			if Mode == "New" {
				rf.EF, _ = excelize.OpenFile(excel_file)
			}
			var task_id int
			task_id = ii
			rwChan := make(chan Msg, 0)
			waitChan := make(chan bool, 0)

			var cur_row int
			cur_row = 2

			go func() {
				for {

					task := <-rwChan
					if task.Cell == "" {
						break
					}
					if Mode == "New" {
						copyImg(task.Cell, task.NewCell, sheet, rf, f, waitChan)
					} else {
						copyImgSame(task.Cell, task.NewCell, rawSheet, sheet, f, waitChan)
					}
					//waitChan <- true
				}
			}()

			go func() {
				wg.Add(1)
				for _, vv := range newList {
					if vv == 0 {
						continue
					}
					if cur_row > maxRow {
						break
					}
					//	fmt.Println(cur_row, maxChan, cur_row%maxChan, "==", task_id)

					if cur_row%maxChan == task_id {
						wg.Add(1)
						fv := vv
						cell := imgCol + strconv.Itoa(fv+1)
						new_cell := imgCol + strconv.Itoa(cur_row)
						rwChan <- *&Msg{Cell: cell, NewCell: new_cell}
						<-waitChan

					}

					cur_row += 1

				}
				rwChan <- *&Msg{Cell: ""}
				wg.Done()
			}()
		}

		//fmt.Println(&rfs[ii].EF)
	}
	time.Sleep(2 * time.Second)
	wg.Wait()

	fmt.Println("endTime:", time.Now().Unix())
	fmt.Println("sumTime:", time.Now().Unix()-startTime)
	// Set active sheet of the workbook.
	f.SetActiveSheet(index)
	// Save spreadsheet by the given path.
	pathnew := excel_file
	if Mode == "New" {
		pathnew = ROOT_PATH + "/export" + util.GetDateSp() + ".xlsx"
	}
	if err := f.SaveAs(pathnew); err != nil {
		fmt.Println(err)
	}

	//fmt.Println(nk)

}

func copyImgSame(cell string, new_cell string, rawSheet string, sheet string, f *excelize.File, waitChan chan bool) {
	defer wg.Done()
	//进入锁

	fmt.Print(new_cell, ",")
	f.SetCellValue(sheet, new_cell, "=INDEX("+rawSheet+"!"+cell+",1,1)")
	waitChan <- true

}

func copyImg(cell string, new_cell string, sheet string, rf ExcelFile, f *excelize.File, waitChan chan bool) {
	defer wg.Done()
	//进入锁

	fmt.Print(new_cell, ",")

	imgName, bytes, err := rf.EF.GetPicture(sheet, cell)
	waitChan <- true
	if err != nil {

		fmt.Println(err, "读取图片错误")
		return
	}

	if imgName != "" {
		ext := path.Ext(imgName)
		obj := strings.Replace(imgName, ext, "", 0)

		err := f.AddPictureFromBytes(sheet, new_cell, `{"x_scale": 0.5, "y_scale": 0.5}`, obj, ext, bytes)
		if err != nil {
			fmt.Println(obj)
			fmt.Println(ext)
			fmt.Println(err)
		}

	}

}

func getClass() ([]string, error) {
	file, err := ioutil.ReadFile(ROOT_PATH + "/list.txt")
	if err != nil {
		fmt.Println(err)
		return []string{""}, err
	}
	//fmt.Println(string(file))
	newLine := os.Getenv("NewLine")
	classes := strings.Split(string(file), newLine)
	return classes, nil

}

//文件路径 ，sheet名称 ,分类所在列
func readExcel(path string, sheet string, colName string) ([][]string, []string, *excelize.File, int) {
	defer func() {
		if err := recover(); err != nil {
			fmt.Printf("%s\n", err)
			ui.MsgBox(Mainwin,
				fmt.Sprintln("错误：", err),
				"")
		}
	}()
	f, err := excelize.OpenFile(path)
	if err != nil {
		fmt.Println(err)
		panic(fmt.Sprintf("读取excel错误", err))
	}
	// Get value from cell by given worksheet name and axis.

	// Get all the rows in the Sheet1.

	rows, err := f.GetRows(sheet)
	maxRow := len(rows)
	if err != nil {
		fmt.Println(err)
		panic(fmt.Sprintf("读取excel错误2", err))
	}
	//fmt.Println(rows)
	imgCol := os.Getenv("ImgCol")
	var imgs [][]byte
	mrows := make([]string, len(rows), len(rows))
	imgs = make([][]byte, len(rows), len(rows))
	rowIndex := getColIndex(colName)
	for i, row := range rows {

		if imgCol != "" {
			imgs[i] = []byte("")
			//_, imgs[i] = f.GetPicture(sheet, imgCol+strconv.Itoa(i))
		}
		if len(row) < rowIndex {
			continue
		}
		mrows[i] = row[rowIndex]

		/*	for _, colCell := range row {

				//	fmt.Print(colCell, "\t")
			}
		*/
		//fmt.Println()
	}

	return rows, mrows, f, maxRow
}

func saveExcel() {
	f := excelize.NewFile()
	// Create a new sheet.
	index := f.NewSheet("Sheet1")
	// Set value of a cell.
	f.SetCellValue("Sheet2", "A2", "Hello world.")
	f.SetCellValue("Sheet1", "B2", 100)
	// Set active sheet of the workbook.
	f.SetActiveSheet(index)
	// Save spreadsheet by the given path.
	if err := f.SaveAs("结果" + util.GetDate() + ".xlsx"); err != nil {
		fmt.Println(err)
	}
}

func getCol(col int) string {
	maps := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
	return maps[col]
}

func getColIndex(col string) int {
	maps := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
	for k, v := range maps {
		if v == col {
			return k
		}
	}
	return -1
}
